ASP.NET Core Web API Introduction - A Brief Discussion on non-RESTful Route Overriding
In non-RESTful style Web APIs, the Controller/Action format is typically used to define most URLs. To avoid repetitive route configuration in every Controller or Action, you can create a BasicController to unify the route settings, as shown below:
[ApiController]
[Route("[controller]/[action]")]
public abstract class BasicController : ControllerBase {
}
public class TestRouteController : BasicController {
// URL:/TestRoute/TestAction
[HttpPost]
public void TestAction() {
}
}By using this approach, you don't need to specify the route again in every Controller or Action. However, if you encounter a situation like mine—where you are participating in a front-end/back-end decoupled project for the first time, are unfamiliar with the company's project architecture, and end up developing API URLs that differ significantly from the existing structure, leading to the front-end team coming after you with knives—while you can use [JsonPropertyName] to handle input and output property names, for cases where the route is defined in the BasicController, if you don't want to go back to setting each Action individually, you have to solve this by overriding different routes (though it's a different story if almost everything is different like in my case).
In ASP.NET Core, the [Route] attribute behaves differently depending on whether it is applied to a Controller or an Action. If applied to a Controller, it overrides the BasicController route setting; if applied to an Action, it concatenates with the Controller's setting. Below are examples of several usage scenarios:
[ApiController]
[Route("[controller]/[action]")]
public abstract class BasicController : ControllerBase {
}
[Route("Override/[action]")]
public class TestRouteController : BasicController {
// Scenario: Controller overrides Route, Action is not processed
// URL: /Override/OverrideController
[HttpPost]
public void OverrideController() {
}
// Common misuse scenario: Both Controller and Action override Route,
// resulting in the Action URL being a concatenation of both routes
// URL: /Override/OverrideAction/Action/OverrideAction
[HttpPost]
[Route("Action/[action]")]
public void OverrideAction() {
}
// Scenario: Action does not want to use the Controller's Route,
// add "/" at the beginning of the Route
// URL: /Action/OnlyAction
[HttpPost]
[Route("/Action/[action]")]
public void OnlyAction() {
}
// Scenario: Action does not want to use the Controller's Route,
// add "~" at the beginning of the Route, same effect as above
// URL: /Action/OnlyAction2
[HttpPost]
[Route("~/Action/[action]")]
public void OnlyAction2() {
}
// Scenario: Simply want to rename the Action
// URL: /Override/Rename
[HttpPost]
[ActionName("Rename")]
public void RenameAction() {
}
}Change Log
- 2024-04-16 Initial document creation.
